#include <rtthread.h>
#include <rtdevice.h>
#include <string.h>
#include <assert.h>
#include <rtconfig.h>
#include "board.h"
#include "at32f435_437.h"
#include "offchip_flash.h"
#include "drv_qspi.h"

#ifdef BSP_USING_QSPI1
#include <sfud.h>
#include "spi_flash_sfud.h"

////////////////////////////////////////////////////////////////////////////////

#define FLASH_EN_PIN    GET_PIN(C, 3)
#define FLASH_CS_PIN    GET_PIN(G, 6)

#define ENABLE          (PIN_HIGH)
#define DISABLE         (PIN_LOW)
#define FLASH_ENABLE(x) rt_pin_write(FLASH_EN_PIN, x)

#define QSPI_BUS_NAME   "qspi1"
#define QSPI_DEV_NAME   "qspi10"
#define FLASH_DEV_NAME  FAL_USING_NOR_FLASH_DEV_NAME

static sfud_flash *sfud_dev = RT_NULL;

////////////////////////////////////////////////////////////////////////////////

static int offchip_flash_init(void)
{
    int ret = RT_ERROR;
    rt_pin_mode(FLASH_EN_PIN, PIN_MODE_OUTPUT);
    FLASH_ENABLE(ENABLE);
    ret = at32_qspi_bus_attach_device(QSPI_BUS_NAME, QSPI_DEV_NAME, 
                                      FLASH_CS_PIN, 4, RT_NULL, RT_NULL);
    if (RT_EOK == ret)
    {
        rt_sfud_flash_probe(FLASH_DEV_NAME, QSPI_DEV_NAME);
        // sfud_dev = rt_sfud_flash_find_by_dev_name(FLASH_DEV_NAME);
    }
    // FLASH_ENABLE(DISABLE);
    return ret;
}
#ifdef UC_GATEWAY_HARDWARE
INIT_ENV_EXPORT(offchip_flash_init);
// INIT_APP_EXPORT(offchip_flash_init);
#endif

////////////////////////////////////////////////////////////////////////////////

int offchip_flash_read(long offset, uint8_t *buf, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    FLASH_ENABLE(ENABLE);
    sfud_read(sfud_dev, OFFCHIP_FLASH_START_ADDR + offset, size, buf);
    FLASH_ENABLE(DISABLE);
    return size;
}

int offchip_flash_write(long offset, const uint8_t *buf, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    int ret = size;
    FLASH_ENABLE(ENABLE);
    if (sfud_write(sfud_dev, OFFCHIP_FLASH_START_ADDR + offset, size, buf) != SFUD_SUCCESS)
    {
        ret = -1;
    }
    FLASH_ENABLE(DISABLE);
    return ret;
}

int offchip_flash_erase(long offset, size_t size)
{
    assert(sfud_dev);
    assert(sfud_dev->init_ok);
    int ret = size;
    FLASH_ENABLE(ENABLE);
    if (sfud_erase(sfud_dev, OFFCHIP_FLASH_START_ADDR + offset, size) != SFUD_SUCCESS)
    {
        ret = -1;
    }
    FLASH_ENABLE(DISABLE);
    return ret;
}

#endif // !#ifdef BSP_USING_QSPI1